package com.zenithmind.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import com.zenithmind.task.mapper.TaskAssignmentMapper;
import com.zenithmind.task.pojo.entity.TaskAssignment;
import com.zenithmind.task.pojo.query.TaskAssignmentQuery;
import com.zenithmind.task.pojo.vo.TaskAssignmentVO;
import com.zenithmind.task.service.TaskAssignmentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 任务分配服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TaskAssignmentServiceImpl extends ServiceImpl<TaskAssignmentMapper, TaskAssignment> implements TaskAssignmentService {

    @Override
    public PageResult<TaskAssignmentVO> getTaskAssignmentPage(TaskAssignmentQuery query, String userId) {
        Page<TaskAssignment> page = query.toPage();

        LambdaQueryWrapper<TaskAssignment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(query.getTaskId()), TaskAssignment::getTaskId, query.getTaskId())
               .eq(StringUtils.hasText(query.getAssigneeId()), TaskAssignment::getAssigneeId, query.getAssigneeId())
               .eq(StringUtils.hasText(query.getAssignerId()), TaskAssignment::getAssignerId, query.getAssignerId())
               .eq(query.getAssignmentType() != null, TaskAssignment::getAssignmentType, query.getAssignmentType())
               .eq(query.getStatus() != null, TaskAssignment::getStatus, query.getStatus())
               .eq(query.getRolePermission() != null, TaskAssignment::getRolePermission, query.getRolePermission());

        // TODO: TaskAssignmentQuery中缺少时间范围字段, 暂注释
        // if (query.getCreateTimeBegin() != null) {
        //     wrapper.ge(TaskAssignment::getCreateTime, query.getCreateTimeBegin());
        // }
        // if (query.getCreateTimeEnd() != null) {
        //     wrapper.le(TaskAssignment::getCreateTime, query.getCreateTimeEnd());
        // }

        wrapper.orderByDesc(TaskAssignment::getCreateTime);

        IPage<TaskAssignment> result = page(page, wrapper);

        List<TaskAssignmentVO> voList = result.getRecords().stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());

        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public TaskAssignmentVO getTaskAssignmentById(String id, String userId) {
        TaskAssignment taskAssignment = getById(id);
        if (taskAssignment == null) {
            throw new BusinessException("任务分配不存在");
        }
        
        return convertToVO(taskAssignment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createTaskAssignment(TaskAssignment taskAssignment, String userId) {
        // 检查是否已存在相同的分配
        LambdaQueryWrapper<TaskAssignment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskAssignment::getTaskId, taskAssignment.getTaskId())
               .eq(TaskAssignment::getAssigneeId, taskAssignment.getAssigneeId())
               .eq(TaskAssignment::getStatus, 1); // 有效状态

        if (count(wrapper) > 0) {
            throw new BusinessException("该用户已被分配此任务");
        }

        // 设置默认值
        if (taskAssignment.getStatus() == null) {
            taskAssignment.setStatus(1); // 待接受
        }
        if (taskAssignment.getAssignmentType() == null) {
            taskAssignment.setAssignmentType(1); // 主要负责人
        }
        if (taskAssignment.getRolePermission() == null) {
            taskAssignment.setRolePermission(2); // 编辑权限
        }

        taskAssignment.setAssignerId(userId);
        taskAssignment.setAssignmentTime(LocalDateTime.now());

        boolean result = save(taskAssignment);
        
        if (result) {
            log.info("用户 {} 创建任务分配: 任务ID={}, 被分配人ID={}", userId, taskAssignment.getTaskId(), taskAssignment.getAssigneeId());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTaskAssignment(TaskAssignment taskAssignment, String userId) {
        TaskAssignment existing = getById(taskAssignment.getId());
        if (existing == null) {
            throw new BusinessException("任务分配不存在");
        }

        // 权限检查
        if (!existing.getAssignerId().equals(userId) && !existing.getAssigneeId().equals(userId)) {
            throw new BusinessException("无权限修改该任务分配");
        }

        boolean result = updateById(taskAssignment);
        
        if (result) {
            log.info("用户 {} 更新任务分配: ID={}", userId, taskAssignment.getId());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTaskAssignment(String id, String userId) {
        TaskAssignment taskAssignment = getById(id);
        if (taskAssignment == null) {
            throw new BusinessException("任务分配不存在");
        }

        // 权限检查
        if (!taskAssignment.getAssignerId().equals(userId)) {
            throw new BusinessException("无权限删除该任务分配");
        }

        boolean result = removeById(id);
        
        if (result) {
            log.info("用户 {} 删除任务分配: ID={}", userId, id);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteTaskAssignments(List<String> ids, String userId) {
        for (String id : ids) {
            deleteTaskAssignment(id, userId);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean acceptTaskAssignment(String id, String userId) {
        TaskAssignment taskAssignment = getById(id);
        if (taskAssignment == null) {
            throw new BusinessException("任务分配不存在");
        }

        if (!taskAssignment.getAssigneeId().equals(userId)) {
            throw new BusinessException("只能接受分配给自己的任务");
        }

        if (taskAssignment.getStatus() != 1) {
            throw new BusinessException("任务分配状态不正确");
        }

        taskAssignment.setStatus(2); // 已接受
        taskAssignment.setAcceptTime(LocalDateTime.now());

        boolean result = updateById(taskAssignment);
        
        if (result) {
            log.info("用户 {} 接受任务分配: ID={}", userId, id);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean rejectTaskAssignment(String id, String reason, String userId) {
        TaskAssignment taskAssignment = getById(id);
        if (taskAssignment == null) {
            throw new BusinessException("任务分配不存在");
        }

        if (!taskAssignment.getAssigneeId().equals(userId)) {
            throw new BusinessException("只能拒绝分配给自己的任务");
        }

        if (taskAssignment.getStatus() != 1) {
            throw new BusinessException("任务分配状态不正确");
        }

        taskAssignment.setStatus(3); // 已拒绝
        taskAssignment.setRejectTime(LocalDateTime.now());
        taskAssignment.setRejectReason(reason);

        boolean result = updateById(taskAssignment);
        
        if (result) {
            log.info("用户 {} 拒绝任务分配: ID={}, 原因={}", userId, id, reason);
        }
        
        return result;
    }

    @Override
    public List<TaskAssignmentVO> getUserTaskAssignments(String userId, Integer status) {
        LambdaQueryWrapper<TaskAssignment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskAssignment::getAssigneeId, userId)
               .eq(status != null, TaskAssignment::getStatus, status)
               .orderByDesc(TaskAssignment::getCreateTime);

        List<TaskAssignment> assignments = list(wrapper);
        
        return assignments.stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());
    }

    @Override
    public List<TaskAssignmentVO> getTaskAssignments(String taskId, String userId) {
        LambdaQueryWrapper<TaskAssignment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskAssignment::getTaskId, taskId)
               .orderByDesc(TaskAssignment::getCreateTime);

        List<TaskAssignment> assignments = list(wrapper);
        
        return assignments.stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());
    }

    /**
     * 转换为VO对象
     */
    private TaskAssignmentVO convertToVO(TaskAssignment taskAssignment) {
        TaskAssignmentVO vo = BeanCopyUtils.copyBean(taskAssignment, TaskAssignmentVO.class);
        
        // 设置状态文本
        vo.setStatusText(getStatusText(taskAssignment.getStatus()));
        
        // 设置分配类型文本
        vo.setAssignmentTypeText(getAssignmentTypeText(taskAssignment.getAssignmentType()));
        
        // 设置角色权限文本
        vo.setRolePermissionText(getRolePermissionText(taskAssignment.getRolePermission()));
        
        return vo;
    }

    /**
     * 获取状态文本
     */
    private String getStatusText(Integer status) {
        switch (status) {
            case 1: return "待接受";
            case 2: return "已接受";
            case 3: return "已拒绝";
            case 4: return "已取消";
            default: return "未知";
        }
    }

    /**
     * 获取分配类型文本
     */
    private String getAssignmentTypeText(Integer assignmentType) {
        switch (assignmentType) {
            case 1: return "主要负责人";
            case 2: return "协作者";
            case 3: return "观察者";
            default: return "未知";
        }
    }

    /**
     * 获取角色权限文本
     */
    private String getRolePermissionText(Integer rolePermission) {
        switch (rolePermission) {
            case 1: return "只读";
            case 2: return "编辑";
            case 3: return "管理";
            default: return "未知";
        }
    }
}
